package com.scnu.recruitment.utils;

import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.SerializedName;
import com.scnu.common.constants.Constant;
import com.scnu.common.domain.dto.PersonalIndexResponse;
import com.scnu.common.domain.po.User;
import com.scnu.common.exception.ServiceException;
import com.scnu.common.exception.UnauthorizedException;
import com.scnu.common.utils.UserContext;
import com.scnu.recruitment.domain.po.ExpOrder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.math.BigDecimal;
import java.net.URI;
import java.security.PrivateKey;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Component
@RequiredArgsConstructor
public class WechatPay {

    private final RestTemplate restTemplate;




    private static final String MCHID = "1711962687";
    private static final String APPID = "wx88b8059bb11d6445";

    private static final String HOST = "https://api.mch.weixin.qq.com";
    private static final String privateKeyFilePath = "apiclient_key.pem";

    private static final String certificateSerialNo= "6A52FE831CBAC67F77EF927E17F2E2129A87FEC7";
    private PrivateKey privateKey=WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);


    public String prepay(ExpOrder expOrder){
        String description = String.format("快递代拿：物件大小：%s，配送方式：%s",expOrder.getExpressSize().getDesc(),expOrder.getDeliveryType().getDesc());


        return this.prepay(String.valueOf(expOrder.getOrderNumber()),expOrder.getTotalFee(), Constant.BACKEND_URL +"/express/order/pay-success",description);
    }


    /**
     *
     * @param outTradeNo
     * @param fee 费用，单位元，两位小数
     * @param notifyUrl
     * @param description
     * @return
     */
    public String prepay(String outTradeNo, BigDecimal fee, String notifyUrl, String description){
        User user = UserContext.getUser();


        String path = "/v3/pay/transactions/jsapi";

        DirectAPIv3JsapiPrepayRequest requestBody = new DirectAPIv3JsapiPrepayRequest();
        requestBody.setAppid(APPID);
        requestBody.setMchid(MCHID);
        requestBody.setDescription(description);
        requestBody.setOutTradeNo(outTradeNo);
        String format = OffsetDateTime.now(ZoneOffset.ofHours(8))
                .plusMinutes(15)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"));
        requestBody.setTimeExpire(format);
        requestBody.setAttach(null);
        requestBody.setNotifyUrl(notifyUrl);
        //设置订单优惠标记
        requestBody.setGoodsTag(null);
        requestBody.setSupportFapiao(true);
        //订单金额，单位为分
        requestBody.setAmount(new CommonAmountInfo(fee.movePointRight(2).longValue(), "CNY"));

        requestBody.setPayer(new JsapiReqPayerInfo(user.getWeixinOpenid()));




        String reqBody = WXPayUtility.toJson(requestBody);
        HttpHeaders headers = new HttpHeaders();

        headers.add("Authorization", WXPayUtility.buildAuthorization(MCHID, certificateSerialNo,privateKey, "POST", path, reqBody));
        headers.add("Content-Type", "application/json");
        headers.add("Accept", "application/json");







        URI uri = UriComponentsBuilder.fromHttpUrl(HOST+path)
                .build(true)
                .toUri();


        HttpEntity<Object> requestEntity = new HttpEntity<>(reqBody, headers);
        ResponseEntity<DirectAPIv3JsapiPrepayResponse> responseEntity = restTemplate.postForEntity(uri, requestEntity, DirectAPIv3JsapiPrepayResponse.class);
        DirectAPIv3JsapiPrepayResponse body = responseEntity.getBody();
        if (body == null) {
            throw new ServiceException("JSAPI下单失败");
        }

        return body.prepayId;

    }

    @Data
    public static class DirectAPIv3JsapiPrepayRequest {
        @SerializedName("appid")
        public String appid;

        @SerializedName("mchid")
        public String mchid;

        @SerializedName("description")
        public String description;

        @SerializedName("out_trade_no")
        public String outTradeNo;

        @SerializedName("time_expire")
        public String timeExpire;

        @SerializedName("attach")
        public String attach;

        @SerializedName("notify_url")
        public String notifyUrl;

        @SerializedName("goods_tag")
        public String goodsTag;

        @SerializedName("support_fapiao")
        public Boolean supportFapiao;

        @SerializedName("amount")
        public CommonAmountInfo amount;

        @SerializedName("payer")
        public JsapiReqPayerInfo payer;

        @SerializedName("detail")
        public CouponInfo detail;

        @SerializedName("scene_info")
        public CommonSceneInfo sceneInfo;

        @SerializedName("settle_info")
        public SettleInfo settleInfo;
    }

    public static class DirectAPIv3JsapiPrepayResponse {
        @SerializedName("prepay_id")
        @JsonProperty("prepay_id")
        public String prepayId;
    }

    @Data
    @AllArgsConstructor
    public static class CommonAmountInfo {
        @SerializedName("total")
        public Long total;

        @SerializedName("currency")
        public String currency;
    }

    @Data
    @AllArgsConstructor
    public static class JsapiReqPayerInfo {
        @SerializedName("openid")
        public String openid;
    }

    public static class CouponInfo {
        @SerializedName("cost_price")
        public Long costPrice;

        @SerializedName("invoice_id")
        public String invoiceId;

        @SerializedName("goods_detail")
        public List<JsapiPrepay.GoodsDetail> goodsDetail;
    }

    public static class CommonSceneInfo {
        @SerializedName("payer_client_ip")
        public String payerClientIp;

        @SerializedName("device_id")
        public String deviceId;

        @SerializedName("store_info")
        public JsapiPrepay.StoreInfo storeInfo;
    }

    public static class SettleInfo {
        @SerializedName("profit_sharing")
        public Boolean profitSharing;
    }

    public static class GoodsDetail {
        @SerializedName("merchant_goods_id")
        public String merchantGoodsId;

        @SerializedName("wechatpay_goods_id")
        public String wechatpayGoodsId;

        @SerializedName("goods_name")
        public String goodsName;

        @SerializedName("quantity")
        public Long quantity;

        @SerializedName("unit_price")
        public Long unitPrice;
    }

    public static class StoreInfo {
        @SerializedName("id")
        public String id;

        @SerializedName("name")
        public String name;

        @SerializedName("area_code")
        public String areaCode;

        @SerializedName("address")
        public String address;
    }






}
